package com.zaofan.mobile.controller;

import com.zaofan.bean.Account;
import com.zaofan.bean.AccountLog;
import com.zaofan.bean.Error;
import com.zaofan.bean.Recharge;
import com.zaofan.cache.CacheManage;
import com.zaofan.constant.StateConstant;
import com.zaofan.constant.TypeConstant;
import com.zaofan.service.AccountLogService;
import com.zaofan.service.AccountService;
import com.zaofan.service.ErrorService;
import com.zaofan.service.RechargeService;
import com.zaofan.utils.C3p0DataSourceUtils;
import com.zaofan.utils.Constants;
import com.zaofan.utils.JPushUtils;
import com.zaofan.utils.SqlBuilderUtils;
import com.zaofan.utils.pay.MD5Util;

import org.apache.commons.dbutils.QueryRunner;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/wei_pay_recharge_notify")
public class WeiPayRechargeController extends HttpServlet {

	private RechargeService rechargeService = new RechargeService();
	private AccountService accountService = new AccountService();
	private AccountLogService accountLogService = new AccountLogService();
	private ErrorService errorService = new ErrorService();

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.err.println("wei pay in ");
		try {
			SortedMap<Object, Object> map = parseXml(request);
            String sign = sign("UTF-8", map,(String)map.get("trade_type"),(String)map.get("appid"));
            if (sign.equals(map.get("sign"))) {
				System.err.println("签名正确");

				if ("SUCCESS".equals(map.get("result_code"))) {
					System.err.println("支付成功");
					String out_trade_no = (String) map.get("transaction_id");
					String orderNo = map.get("out_trade_no").toString().trim().split("t")[0];
					BigDecimal price = new BigDecimal((String) map.get("total_fee")).divide(new BigDecimal(100));
					Recharge recharge = rechargeService.findByRechargeNo(orderNo);
					if (recharge == null) {
						Error error = new Error();
						error.setAddTime(new Date());
						error.setError("微信支付出现问题,微信订单:" + orderNo + ",无法匹配不到系统的充值信息");
						error.setOrderNo(out_trade_no);
						errorService.add(error);
					} else {
						if (recharge.getPayState() == 2) {
							sendResult("SUCCESS", response);
							return;
						}
						Connection connection = C3p0DataSourceUtils.getConnection();
						try {
							connection.setAutoCommit(false);
							// 更新订单状态
							String sql = "update " + Recharge.class.getSimpleName().toLowerCase() + " set payState = "
									+ StateConstant.ORDER_PAY_STATE_PAY + ",state = " + StateConstant.ORDER_STATE_PAY
									+ ",payType='微信支付' where rechargeNo = '" + recharge.getRechargeNo() + "'";
							QueryRunner runner = new QueryRunner();
							runner.update(connection, sql);
							// 增加账户记录
							Account account = accountService.findById(recharge.getAccountId());
							if (account == null) {
								try {
									connection.rollback();
								} catch (SQLException e1) {
									e1.printStackTrace();
								}
								Error error = new Error();
								error.setAddTime(new Date());
								error.setError("微信支付出现问题,微信订单:" + out_trade_no + ",无法匹配不到系统的用户信息");
								error.setOrderNo(recharge.getRechargeNo());
								errorService.add(error);
							} else {
								AccountLog log = new AccountLog();
								log.setAccountId(account.getId());
								log.setAccountMobile(account.getMobile());
								log.setAddTime(new Date());
								log.setAfterMoney(account.getMoney().add(price));
								log.setBeforeMoney(account.getMoney());
								log.setMoney(recharge.getMoney());
								log.setType(TypeConstant.log_type_rechage_weipay);
								account.setMoney(account.getMoney().add(price));
								sql = SqlBuilderUtils.builderInsertSql(AccountLog.class, log);
								runner.update(connection, sql);
								// 活动判断
								if (isInActivity(recharge.getCityId())) {
//									BigDecimal free = price.divide(new BigDecimal(100)).setScale(
//											0,BigDecimal.ROUND_FLOOR).multiply(new BigDecimal(100));
									BigDecimal free = new BigDecimal(0);
									if(price.compareTo(new BigDecimal(500))>=0){
										free = new BigDecimal(150);
									}else if (price.compareTo(new BigDecimal(300))>=0){
										free = new BigDecimal(80);
									}else if (price.compareTo(new BigDecimal(200))>=0){
										free = new BigDecimal(50);

									}else if (price.compareTo(new BigDecimal(100))>=0){
										free = new BigDecimal(20);
									}

									if (free.compareTo(new BigDecimal(0)) > 0) {
										log = new AccountLog();
										log.setAccountId(account.getId());
										log.setAccountMobile(account.getMobile());
										log.setAddTime(new Date());
										log.setAfterMoney(account.getMoney().add(free));
										log.setBeforeMoney(account.getMoney());
										log.setMoney(free);
										log.setType(TypeConstant.log_type_rechage_return_activity);
										sql = SqlBuilderUtils.builderInsertSql(AccountLog.class, log);
										runner.update(connection, sql);
										account.setMoney(account.getMoney().add(free));
									}
								};
								sql = SqlBuilderUtils.builderUpdateSql(Account.class, account);
								runner.update(connection, sql);
							}
							connection.commit();
                            JPushUtils.sendRechargeSuccess(recharge, account);
                        } catch (Exception e) {
							try {
								connection.rollback();
							} catch (SQLException e1) {
								e1.printStackTrace();
							}
							e.printStackTrace();
							return;
						} finally {
							try {
								connection.close();
							} catch (SQLException e) {
								e.printStackTrace();
							}
						}
					}
				} else {
					System.err.println("支付失败");
				}
				sendResult("SUCCESS", response);
				return;
			} else {
				System.err.println("签名失败");
			}
		} catch (Exception e2) {
		}
		sendResult("FAIL", response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	public static SortedMap<Object, Object> parseXml(HttpServletRequest request) throws Exception {
		// 解析结果存储在HashMap
		SortedMap<Object, Object> map = new TreeMap<Object, Object>();
		InputStream inputStream = request.getInputStream();
		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		List<Element> elementList = root.elements();
		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());
		// 释放资源
		inputStream.close();
		inputStream = null;
		return map;
	}

    public static String sign(String characterEncoding, SortedMap<Object, Object> parameters,String type,String appid) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序（升序）
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        if (type.equals("JSAPI")) {
			if(appid.equals(Constants.WX_APP_ID)){
				sb.append("key=" + Constants.API_KEY);
			}else{
				sb.append("key=" + Constants.WXAPI_KEY);
			}
        }else{
            sb.append("key=" + Constants.API_KEY);
        }
        System.out.println("签名参数="+sb.toString());
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

	public void sendResult(String result, HttpServletResponse response) throws IOException {
		String s = "<xml><return_code><![CDATA[" + result
				+ "]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
		response.getWriter().println(s);
	}

	public boolean isInActivity(Integer cityId) {
		if (CacheManage.setting.getRechargeReturn() == 1) {
			if (cityId == 0 || cityId == 2 || cityId == 1) {
				return true;
			}
		}
		return false;
	}

}
